<?php
/**
 * @link https://www.kancloud.cn/cleverstone/ymb2
 * @copyright Copyright (c) 2020 Yii Manager Software LLC
 */

namespace backend\controllers;

use builder\base\BaseController;
use builder\helper\App;
use builder\helper\H5;
use builder\helper\T;
use builder\table\TableBuilder;
use common\models\Admin;
use common\models\AppLogs;
use common\models\Tlog;

/**
 * 应用和操作日志
 * @author cleverstone
 * @since ym2.0
 */
class LogController extends BaseController
{
    public $actionVerbs = [
        'app' => ['GET'],
        'delete' => ['POST'],
        'app-message' => ['GET'],
        'operation' => ['GET'],
        'odelete' => ['POST'],
    ];

    /**
     * 应用日志列表
     * @return string
     * @throws \yii\base\InvalidConfigException
     */
    public function actionApp()
    {
        $table = TableBuilder::instance(['id' => 'Log_App']);

        if ($this->isAjax) {
            $table->setQuery(function () {
                $query = AppLogs::query();

                $params = $this->filteredGet;
                [$startAt, $endAt] = T::rangeDateSplit($params['created_at'] ?? null);

                $keywordWhere = [];
                if (isset($params['keyword']) && $params['keyword'] !== '') {
                    switch ($params['k_type']) {
                        case 'client':
                            $keywordWhere = ['like', 'prefix', $params['keyword']];
                            break;
                        case 'cates':
                            $keywordWhere = ['like', 'category', $params['keyword']];
                            break;
                        case 'cont':
                            $keywordWhere = ['like', 'message', $params['keyword']];
                            break;
                    }
                }

                $query->andFilterWhere([
                    'and',
                    $keywordWhere,
                    ['level' => $params['level'] ?? null],
                    ['between', 'created_at', $startAt, $endAt],
                ]);

                return $query;
            })
                ->setOrderBy(['created_at' => SORT_DESC])
                ->setColumns([
                    'id',
                    'Level_Str' => function ($row) {
                        $level = $row['level'];
                        return H5::badgeDot(AppLogs::LEVEL_LABELS_MAP[$level], AppLogs::LEVEL_COLORS_MAP[$level]);
                    },
                    'category',
                    'business_type',
                    'prefix',
                    'created_at',
                ]);
        } else {
            $t = date('t');
            App::setViewBreadcrumb([
                ['name' => '日志/记录'],
                ['name' => '应用日志', 'url' => 'log/app'],
            ]);

            $startAt = T::dayToAbsoluteDate(-30, false, true);
            $endAt = date('Y-m-d 23:59:59');
            $table->setTitle('应用日志')
                ->setLimit(20)
                ->setTableHead([
                    $this->tableHead->field('id')->title('ID'),
                    $this->tableHead->field('category')->title('种类')->minWidth(150),
                    $this->tableHead->field('business_type')->title('业务类型')->minWidth(150),
                    $this->tableHead->field('Level_Str')->title('级别')->minWidth(100),
                    $this->tableHead->field('prefix')->title('客户端')->minWidth(450),
                    $this->tableHead->field('created_at')->title('记录日期')->minWidth(150),
                    $this->tableHead->toolbar()->title('操作项')->fixedNone()->width(100),
                ])
                ->setRowOperation([
                    $this->rowOperation->modal('日志详情')->title('查 看')->route('log/app-message')->width(1000)->height(670),
                ])
                ->setToolbarCustom([
                    $this->toolbarCustom->ajax()->title('删除半年前日志')->route('log/delete')->btnClass('layui-btn-danger')->method('post'),
                ])
                ->setToolbarFilter([
                    'created_at' => $this->toolbarFilter->datetime()->label('记录日期')->placeholder('请选择')->defaultValue("$startAt / $endAt")->uiClass('w-auto float-none')->style('width:280px;')->quickChoice(['昨日' => T::createRangeDate('-1 day', '-1 day'), '近3日' => T::createRangeDate('-2 days'), '近7日' => T::createRangeDate('-6 days'), '近'.$t.'日' => T::createRangeDate('-'.($t-1).' days')]),
                    'level' => $this->toolbarFilter->select()->label('日志等级')->placeholder('请选择')->options(AppLogs::LEVEL_LABELS_MAP)->uiConfig('minimumResultsForSearch', -1)->uiClass('w-md-350'),
                    'k_type' => $this->toolbarFilter->select()->label(null)->options(['client' => '客户端', 'cates' => '日志种类', 'cont' => '日志内容'])->uiConfig('width', '100px')->uiClass('w-100px')->style(['margin-right' => '-10px'])->uiConfig('allowClear', false)->defaultValue('client'),
                    'keyword' => $this->toolbarFilter->text()->label(null)->placeholder('客户端/日志种类/日志内容')->uiClass('w-280'),
                ])
                ->setColumnFilter()
                ->setToolbarRefresh();
        }

        return $table->render();
    }

    /**
     * 删除五个月前的应用日志
     * @return \yii\web\Response
     */
    public function actionDelete()
    {
        $lastFive = date('Y-m-d H:i:s', strtotime('-6 months'));
        $result = AppLogs::deleteAll(['<=', 'created_at', $lastFive]);

        if ($result) {
            return $this->asOk('删除半年前的【应用日志】成功，删除数量:' . $result . '条。');
        }

        return $this->asOk('半年前【应用日志】为空，不需要删除。');
    }

    /**
     * 信息
     * @param int $id 日志ID
     * @return string
     * @throws \Throwable
     */
    public function actionAppMessage($id)
    {
        $detail = AppLogs::query(['message'])->where(['id' => $id])->one();
        if (empty($detail)) {
            return $this->renderContentX(H5::alert('空', 'info'));
        }

        App::registerDynamicAsset(['highlight'], function () {
            \builder\bundle\Highlight::$curTheme = 'xt256';
        });
        return $this->renderContentX(
            H5::highlightGrammar($detail['message'], 'php', ['style' => 'white-space:pre;height:100%;'])
        );
    }

    /**
     * 操作日志列表
     * @return string
     * @throws \Throwable
     */
    public function actionOperation()
    {
        $userColumns = Admin::query(['username'])->indexBy('id')->column();
        $userColumns[0] = Admin::SYSTEM_NAME;
        ksort($userColumns);

        $table = TableBuilder::instance(['id' => 'Log_Operation']);

        if ($this->isAjax) {
            $table->setColumnDependency($userColumns)
                ->setQuery(function () {
                    $query = Tlog::query();

                    $params = $this->filteredGet;
                    [$startAt, $endAt] = T::rangeDateSplit($params['created_at'] ?? null);

                    $keywordWhere = [];
                    if (isset($params['keyword']) && $params['keyword'] !== '') {
                        switch ($params['k_type']) {
                            case 'a_rout':
                                $keywordWhere = ['like', 'route', $params['keyword']];
                                break;
                            case 't_type':
                                $keywordWhere = ['like', 'category', $params['keyword']];
                                break;
                            case 'client':
                                $keywordWhere = ['like', 'prefix', $params['keyword']];
                                break;
                            case 'cont':
                                $keywordWhere = ['like', 'message', $params['keyword']];
                                break;
                        }
                    }

                    $query->andFilterWhere([
                        'and',
                        $keywordWhere,
                        ['aid' => $params['aid'] ?? null],
                        ['between', 'created_at', $startAt, $endAt],
                    ]);

                    return $query;
                })
                ->setOrderBy(['created_at' => SORT_DESC])
                ->setColumns([
                    'id',
                    'Name_Str' => function ($row, $dependency) {
                        return !empty($dependency[$row['aid']]) ? $dependency[$row['aid']] : '-';
                    },
                    'route',
                    'category',
                    'message',
                    'prefix',
                    'created_at',
                ]);
        } else {
            $t = date('t');
            App::setViewBreadcrumb([
                ['name' => '日志/记录'],
                ['name' => '操作日志', 'url' => 'log/operation'],
            ]);

            $startAt = T::dayToAbsoluteDate(-30, false, true);
            $endAt = date('Y-m-d 23:59:59');
            $table->setTitle('操作日志列表')
                ->setLimit(20)
                ->setTableHead([
                    $this->tableHead->field('id')->title('ID'),
                    $this->tableHead->field('Name_Str')->title('管理员')->width(120),
                    $this->tableHead->field('route')->title('访问路由')->width(200),
                    $this->tableHead->field('category')->title('操作类型')->width(200),
                    $this->tableHead->field('message')->title('日志内容')->minWidth(300),
                    $this->tableHead->field('prefix')->title('客户端')->width(380),
                    $this->tableHead->field('created_at')->title('操作日期')->width(150),
                ])
                ->setToolbarCustom([
                    $this->toolbarCustom->ajax()->title('删除半年前日志')->route('log/odelete')->btnClass('layui-btn-danger')->method('post'),
                ])
                ->setToolbarFilter([
                    'created_at' => $this->toolbarFilter->datetime()->label('操作日期')->placeholder('请选择')->defaultValue("$startAt / $endAt")->uiClass('w-auto float-none')->style('width:280px;')->quickChoice(['昨日' => T::createRangeDate('-1 day', '-1 day'), '近3日' => T::createRangeDate('-2 days'), '近7日' => T::createRangeDate('-6 days'), '近'.$t.'日' => T::createRangeDate('-'.($t-1).' days')]),
                    'aid' => $this->toolbarFilter->select()->label('管理员')->placeholder('请选择')->options($userColumns)->uiClass('w-md-350'),
                    'k_type' => $this->toolbarFilter->select()->label(null)->options(['a_rout' => '访问路由', 't_type' => '操作类型', 'client' => '客户端', 'cont' => '日志内容'])->uiConfig('width', '100px')->uiClass('w-100px')->style(['margin-right' => '-10px'])->uiConfig('allowClear', false)->defaultValue('a_rout'),
                    'keyword' => $this->toolbarFilter->text()->label(null)->placeholder('访问路由/操作类型/客户端/日志内容')->uiClass('w-280'),
                ])
                ->setColumnFilter()
                ->setToolbarRefresh();
        }

        return $table->render();
    }

    /**
     * 删除五月以前的操作日志
     * @return \yii\web\Response
     */
    public function actionOdelete()
    {
        $lastFive = date('Y-m-d H:i:s', strtotime('-6 months'));
        $result = Tlog::deleteAll(['<=', 'created_at', $lastFive]);
        if ($result) {
            return $this->asOk('删除半年前的【操作日志】成功，删除数量:' . $result . '条。');
        }

        return $this->asOk('半年前【操作日志】为空，不需要删除。');
    }
}